<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>call and apply研究</title>
</head>
<body>


<script>

    function person1(name, age) {
        this.name = name;
        this.age = age;
        this.hi = function () {
            console.log('person1,hi:' + this.name);
        }
    }

    function student1(name, age, grade) {
        //console.log(arguments[0]);//如何获取参数名称
        person1.apply(this, arguments);
        this.grade = grade;
    }

    var ss1 = new student1('zhangsan', '21', '一年级');

    console.log(ss1);
    ss1.hi();


    function person(name, age) {
        this.name = name;
        this.age = age;
        this.hi = function () {
            console.log('person,hi:' + this.name);
        }
    }

    function student(name, age, grade) {
        person.call(this, name, age);
        this.grade = grade;
    }

    var s1 = new student('zhangsan', '21', '一年级');

    console.log(s1);
    s1.hi();

    var p1 = new person('李二狗', '12');
    console.log(p1);
    p1.hi();

    // 将调用apply的对象的方法和属性，都赋给this。

    console.log('---------------------------------------------------------------------------------');

    var cat = function () {

    };

    cat.prototype = {
        food: 'fish',
        say: function () {
            console.log('i love ' + this.food);
        }
    }

    var blockCat = new cat();
    blockCat.say();

    var whiteDog = {food: 'bone'};
    blockCat.say.call(whiteDog);


    var fn = function () {

    }
    var ary = [];

    var class2type = {};

    function type(obj) {
        if (obj == null) {
            return obj + "";
        }
        // Support: Android<4.0, iOS<6 (functionish RegExp)
        return typeof obj === "object" || typeof obj === "function" ?
        class2type[toString.call(obj)] || "object" :
                typeof obj;
    }

    function A() {
        this.name = 'aaa';
        this.say = function () {
            console.log("我是1" + this.name);
        }
    }
    function B() {
        this.name = 'bbb';
        this.say = function () {
            console.log("我是2" + this.name);
        }
    }
    var a = new A();
    var b = new B();
    a.say.call(b);


    /**
     如何理解和熟练运用js中的call及apply？
     有时候看一两个关于apply或call的小例子，感觉能够理解一点点
     但是下次碰到又要纠结半天才能转过弯来～而且不知道怎么应用到实际工作当中去～


     LZ要先明白存在call和apply的原因，才能记得牢一点：
     在javascript OOP中，我们经常会这样定义：

     function cat(){
    }
     cat.prototype={
        food:"fish",
        say: function(){
            alert("I love "+this.food);
        }
    }

     var blackCat = new cat;
     blackCat.say();

     但是如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法，那么我们可以通过call或apply用blackCat的say方法：blackCat.say.call(whiteDog);
     所以，可以看出call和apply是为了动态改变this而出现的，当一个object没有某个方法，但是其他的有，我们可以借助call或apply用其它对象的方法来操作。
     用的比较多的，通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过：
     var domNodes =  Array.prototype.slice.call(document.getElementsByTagName("*"));
     这样domNodes就可以应用Array下的所有方法了。其他的就不提了，讲多了反而迷惑。

     作者：杨志
     链接：https://www.zhihu.com/question/20289071/answer/14644278
     来源：知乎
     著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。*/



    /**
     * call 和 apply 的区别

     obj.call(thisObj, arg1, arg2, ...);
     obj.apply(thisObj, [arg1, arg2, ...]);

     两者作用一致，都是把obj(即this)绑定到thisObj，这时候thisObj具备了obj的属性和方法。或者说thisObj『继承』了obj的属性和方法。唯一区别是apply接受的是数组参数，call接受的是连续参数

     作者：知乎用户
     链接：https://www.zhihu.com/question/20289071/answer/80892838
     来源：知乎
     著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。




     作者：知乎用户
     链接：https://www.zhihu.com/question/20289071/answer/14754911
     来源：知乎
     著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。

     apply: Function.prototype.apply
     call:Function.prototype.call
     NOTE: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments. call 和 apply 的区别只在于这两个函数接受的参数形式不同。

     Example: 判断一个变量是不是Array
     var a = {};
     var b = []
     Object.prototype.toString.call(a);
     // 输出为： "[object Object]"
     Object.prototype.toString.call(a);
     // 输出为： "[object Array]"

     update: 2013.5.4使用call和apply方法，可以改变对象方法的运行环境，例如，有一个类Man



     function Man() {}
     Man.prototype = {
    valet: false,
    wakeUp: function(event) {
        console.log(this.valet + "? Some breakfase, please.");
    }
    };

     var wooster = new Man();

     //get "undefined? Some breakfast, please
     var button = document.getElementById('morning');
     button.addEventListener(
     "click",
     wooster.wakeUp,
     false
     );

     //使用apply来改变 wakeUp 的上下文环境，即 wakeUp 中的this
     var button = document.getElementById('morning2');
     button.addEventListener(
     "click",
     function() {
        Man.prototype.wakeUp.apply(wooster, arguments);
    },
     false
     );

     */




</script>
<script src="../modules/jquery.js"></script>
</body>
</html>